from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template as django_template
from google.appengine.ext.webapp.util import run_wsgi_app
from model import model
from model import datetime_translator as dt
import datetime
import os

class EdenPunch(webapp.RequestHandler):
    def _login(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))

    def _get_template_path(self, template_name):
        path = os.path.join(os.path.dirname(__file__), 'templates/%s' % template_name)
        return path

    def _render_template(self, template_name, template_args={}):
        """render and write out the template including it's scaffold"""
        path = self._get_template_path(template_name)
        # add the request object by default to all requests at the view
        template_args["request"] = self.request
        content = django_template.render(path, template_args)
        scaffold_path = self._get_template_path("scaffold.html")
        page_name = template_name.split(".")[0].title()
        html_title = "Eden Punch! - %s" % page_name
        scaffold_args = {'title': html_title,
                         'page_name': page_name,
                         'page_content': content,
                         "error": self.request.get("error")}
        self.response.out.write(django_template.render(scaffold_path, scaffold_args))

    def _get_projects_for_select(self):
        return [{'name': p.name, 'key': p.key()} for p in model.get_projects(get_archived=False)]

    def get(self):
        self._login()
        template_args = {"projects": self._get_projects_for_select()}
        if not len(template_args["projects"]):
            self.redirect("/admin/projects")
        result = model.is_clocked_in()
        if result:
            key, project_name = result
        else:
            key = ""
            project_name = ""
        template_args["clocked_in"] = key
        template_args['project_name'] = project_name
        input_daystart_dt_utc, dayafter_daystart_dt_utc = dt.get_today_daystart_and_tomorrow_in_utc()
        sums, grand_sum = model.get_project_sums(input_daystart_dt_utc, dayafter_daystart_dt_utc, True)
        use_sums = []
        for sum in sums:
            if not sum["sum"] == "00.00" or sum["project"] == project_name:
                use_sums.append(sum)
        template_args["todays_sums"] = use_sums
        template_args["todays_punches"] = self._get_todays_punches(input_daystart_dt_utc, dayafter_daystart_dt_utc)
        template_args["grand_sum"] = grand_sum
        template_args["workweek_sum"] = "%2.2f" % model.get_workweek_hours(input_daystart_dt_utc)
        self._render_template("index.html", template_args)

    def _ftp(self, input_datetime):
        return input_datetime.time().strftime("%H:%M:%S")

    def _get_todays_punches(self, start, end):
        punches = model.get_todays_punches(start, end)
        return_list = []
        for punch in punches:
            row_dict = {"project_name": punch.project.name,
                        "in_datetime": self._ftp(dt.convert_to_localtime(punch.in_out_datetimes[0])),
                        "out_datetime": self._ftp(dt.convert_to_localtime(punch.in_out_datetimes[1])),
                        "key": punch.key()}
            return_list.append(row_dict)
        return return_list

    def post(self):
        self._login()
        key = self.request.get("key")
        project_key = self.request.get("project_key")
        now = datetime.datetime.now()
        if key:
            # clocking out
            punch = model.get_punch(key)
            model.save_punch(project_key,
                in_utc_datetime=punch.in_out_datetimes[0],
                out_utc_datetime=now, punch_key=key)
        else:
            # clocking in
            model.save_punch(project_key, in_utc_datetime=now)
        self.redirect("/")


class Admin(EdenPunch):
    def get(self):
        self._login()
        self._render_template("admin.html")

    def _render_template(self, template_name, template_args={}):
        template_name = "admin/" + template_name
        EdenPunch._render_template(self, template_name, template_args)


class Reports(EdenPunch):
    def get(self):
        self._login()
        self._render_template("reports.html")


class Workweek(Admin):
    def post(self):
        self._login()
        model.save_workweek(self.request.get("start_day"),
            self.request.get("end_day"))
        self.redirect("/admin/workweek")

    def get(self):
        self._login()
        template_args = {"workweek": model.get_workweek()}
        self._render_template("workweek.html", template_args)


class Report(EdenPunch):
    def _get_datetime_from_js_date(self, jsdate):
        return datetime.datetime.strptime(jsdate, "%m/%d/%Y")

    def get(self):
        self._login()
        self._render_template("report.html")

    def post(self):
        self._login()
        # do report generation
        table_rows = []
        template_args = {"from": self.request.get("from"),
                         "to": self.request.get("to")}
        date_list = dt.get_date_range(self.request.get("from"), self.request.get("to"))
        for date_obj in date_list:
            input_ds_dt_utc, tom_ds_dt_utc = dt.get_daystart_and_tomorrow_in_utc(date_obj)
            table_row = {"date": date_obj.strftime("%Y-%m-%d")}
            table_row["project_sums"], tmp = model.get_project_sums(input_ds_dt_utc, tom_ds_dt_utc)
            table_rows.append(table_row)
        template_args["table_rows"] = table_rows

        start_date = date_list[0]
        end_date = date_list[-1]
        start_utc = dt.get_daystart_and_tomorrow_in_utc(start_date)[0]
        end_utc = dt.get_daystart_and_tomorrow_in_utc(end_date)[-1]
        template_args["table_sums"], template_args["grand_sum"] = model.get_project_sums(start_utc, end_utc)
        self._render_template("report.html", template_args)


class Edit(EdenPunch):
    def _fedit_dt(self, dt):
        return dt.strftime("%Y-%m-%d %H:%M:%S")

    def get(self):
        self._login()
        key = self.request.get("key")
        punch = model.get_punch(key)
        template_args = {"project_name": punch.project.name,
                         "projects": self._get_projects_for_select(),
                         "in_string": self._fedit_dt(dt.convert_to_localtime(punch.in_out_datetimes[0])),
                         "out_string": self._fedit_dt(dt.convert_to_localtime(punch.in_out_datetimes[1])),
                         "key": punch.key()}
        self._render_template("edit.html", template_args)

    def post(self):
        self._login()
        key = self.request.get("key")
        delete = self.request.get("delete_punch")
        if delete and key:
            model.delete_punch(key)
        else: # save
            in_dt = dt.convert_to_UTC(dt.string_to_datetime(self.request.get("in_string")))
            out_local_dt = dt.string_to_datetime(self.request.get("out_string"))
            if out_local_dt == model.NO_CLOCKOUT_DATETIME:
                out_dt = out_local_dt
            else:
                out_dt = dt.convert_to_UTC(out_local_dt)
            project_key = self.request.get("project_key")
            model.save_punch(project_key,
                in_utc_datetime=in_dt, out_utc_datetime=out_dt,
                punch_key=key)
        self.redirect("/")


class Projects(Admin):
    def get(self):
        self._login()
        key = self.request.get("key")
        template_args = {}
        if key:
            project = model.get_project(key)
            template_args["key"] = key
            template_args["name"] = project.name
            template_args["archived"] = project.archived
        template_args["projects"] = model.get_projects(all=True)
        self._render_template("project.html", template_args)

    def post(self):
        self._login()
        # save the project
        key = self.request.get("key")
        delete = self.request.get("delete_project")
        if delete and key:
            # delete only if there are no punches
            if not model.punches_in_project(key):
                model.delete_project(key)
            else:
                self.redirect(
                    "/admin/projects?key=%s&error=Cannot delete this project as it has punches associated with it." % key)
                return
        else: # save
            name = self.request.get("name")
            archived = self.request.get("archived")
            if archived == "True":
                archived = True
            else:
                archived = False
            model.save_project(name, key, archived)
        self.redirect("/admin/projects")


application = webapp.WSGIApplication([
    ('/', EdenPunch),
    ('/reports', Reports),
    ('/reports/report', Report),
    ('/admin', Admin),
    ('/admin/projects', Projects),
    ('/admin/workweek', Workweek),
    ('/edit', Edit),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()
